package com.cn.sl.server.common.dao.impl

import cn.dev33.satoken.stp.StpUtil
import com.cn.sl.server.common.dao.BaseDao
import com.cn.sl.server.common.model.BaseEntity
import com.cn.sl.server.common.model.QSoftDeleteEditableEntity
import com.cn.sl.server.common.model.SoftDeleteEditableEntity
import com.cn.sl.server.common.repository.BaseRepository
import com.querydsl.core.BooleanBuilder
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.repository.findByIdOrNull
import java.time.LocalDateTime

abstract class SoftDeleteBaseDaoImpl<
        T : SoftDeleteEditableEntity<UserEntity>,
        R : BaseRepository<T>,
        UserEntity : BaseEntity,
        > :
    BaseDaoImpl<T, R>() {

    abstract fun getEntity(): QSoftDeleteEditableEntity

    override fun deleteById(id: Long) {
        getRepository().findByIdOrNull(id)?.let {
            it.del = true
            it.deletedById = StpUtil.getLoginIdAsLong()
            it.deletedTime = LocalDateTime.now()
            getRepository().save(it)
        }
    }

    override fun deleteAllById(ids: List<Long>) {
        val entities = getRepository().findAllById(ids)
        entities.forEach {
            it.del = true
            it.deletedById = StpUtil.getLoginIdAsLong()
            it.deletedTime = LocalDateTime.now()
        }
        getRepository().saveAll(entities)
    }

    override fun delete(entity: T) {
        entity.del = true
        entity.deletedById = StpUtil.getLoginIdAsLong()
        entity.deletedTime = LocalDateTime.now()
        getRepository().save(entity)
    }

    override fun findAll(): List<T> {
        return getRepository().findAll(getEntity().del.eq(false)).toList()
    }

    override fun findAll(sort: Sort): List<T> {
        return getRepository().findAll(getEntity().del.eq(false), sort).toList()
    }

    override fun findAll(booleanBuilder: BooleanBuilder): List<T> {

        booleanBuilder.and(getEntity().del.eq(false))

        return getRepository().findAll(booleanBuilder).toList()
    }

    override fun findAll(booleanBuilder: BooleanBuilder, sort: Sort): List<T> {

        booleanBuilder.and(getEntity().del.eq(false))

        return getRepository().findAll(booleanBuilder, sort).toList()
    }

    override fun deleteAll() {
        val entities = getRepository().findAll()
        entities.forEach {
            it.del = true
            it.deletedById = StpUtil.getLoginIdAsLong()
            it.deletedTime = LocalDateTime.now()
        }
        getRepository().saveAll(entities)
    }

    override fun deleteAll(entities: Collection<T>) {
        entities.forEach {
            it.del = true
            it.deletedById = StpUtil.getLoginIdAsLong()
            it.deletedTime = LocalDateTime.now()
        }
        getRepository().saveAll(entities)
    }

    override fun findAll(act: () -> BaseDao.PageQueryAct): Page<T> {
        val (booleanBuilder, page, pageSize, sort) = act()

        booleanBuilder.and(getEntity().del.eq(false))

        return getRepository().findAll(
            booleanBuilder,
            PageRequest.of(page - 1, pageSize, sort)
        )
    }
}